#ifndef __EVENTS_H__
#define __EVENTS_H__

#include <memory>

#include "GameEnum.h"
#include "Game/SignTextData.hpp"
#include "entt/entity/entity.hpp"
#include "Engine/Ray3.h"
#include "Engine/Vector3.hpp"

using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    struct IInventory;
    struct ComponentPlayer;
    struct ComponentAttacker;
    struct ComponentBody;
    struct ComponentCreature;
    struct ComponentHealth;
    struct ComponentMiner;

    class PlayerData;

    class IEvent
    {
    };

    class IInventoryEvent : public IEvent
    {
    public:
        inline virtual bool playerDrop(ComponentPlayer *componentPlayer)
        {
            return true;
        }
        inline virtual bool playerDrapDrop(ComponentPlayer *componentPlayer, const Vector3 &dropVelocity, IInventory *inventory, uint32_t slotIndex, uint32_t count)
        {
            return true;
        }
        inline virtual bool playerHandleMoveItem(std::shared_ptr<PlayerData> playerData, IInventory *sourceInventory, uint32_t sourceSlotIndex, IInventory *targetInventory, int32_t targetSlotIndex, uint32_t count)
        {
            return true;
        }
        inline virtual bool playerHandleDragDrop(std::shared_ptr<PlayerData> playerData, IInventory *sourceInventory, uint32_t sourceSlotIndex, DragMode dragMode, IInventory *targetInventory, uint32_t targetSlotIndex, bool processingOnly)
        {
            return true;
        }
    };

    class ISignEvent : public IEvent
    {
    public:
        inline virtual bool playerTouchSign(std::shared_ptr<PlayerData> playerData, const Point3 &point)
        {
            return true;
        }
        inline virtual bool playerEditSign(std::shared_ptr<PlayerData> playerData, SignTextData &signTextData)
        {
            return true;
        }
    };

    class IInventoryOpenEvent : public IEvent
    {
    public:
        inline virtual bool openInventory(std::shared_ptr<PlayerData> playerData, IInventory *inventory) 
        {
            return true;
        }
        inline virtual bool openPointInventory(std::shared_ptr<PlayerData> playerData, const Point3 &point, IInventory *inventory) 
        {
            return true;
        }
    };

    class IPlayerEvent : public IEvent
    {
    public:
        inline virtual bool cmdFrontMessage(std::shared_ptr<PlayerData> playerData, std::string &message, std::vector<uint8_t> &toClients)
        {
            return true;
        }
        inline virtual bool message(std::shared_ptr<PlayerData> playerData, std::string &message, std::vector<uint8_t> &toClients)
        {
            return true;
        }
        inline virtual bool playerMove(std::shared_ptr<PlayerData> playerData, const Vector3 &position)
        {
            return true;
        }
        inline virtual bool playerPlaceBlock(ComponentPlayer *componentPlayer, const Point3 &point, int32_t placeBlockValue)
        {
            return true;
        }
        inline virtual bool playerBreakBlock(ComponentPlayer *componentPlayer, const Point3 &point, int32_t digBlockValue, int32_t toolLevel)
        {
            return true;
        }
        inline virtual void playerRestart(ComponentPlayer *componentPlayer) {}
        inline virtual bool onUse(ComponentMiner *componentMiner, const Ray3& ray)
        {
            return true;
        }
        inline virtual bool onAim(ComponentMiner *componentMiner, const Ray3& ray, AimState state)
        {
            return true;
        }
    };

    class ICreatureEvent : public IEvent
    {
    public:
        inline virtual bool hitBody(ComponentAttacker* attacker, ComponentBody *body, const Vector3 &hitPosition, const Vector3 &hitDirection)
        {
            return true;
        }
        inline virtual bool injureEntity(ComponentHealth *health, float amount, entt::entity attackerEntity, bool realInjure, const std::string &cause, InjureType injureType)
        {
            return true;
        }
        inline virtual bool entityDeath(ComponentHealth *health, float amount, entt::entity attackerEntity, const std::string &cause)
        {
            return true;
        }
        // 掉落物品，返回 false 时身上的东西不会掉落
        inline virtual bool dropAllItems(entt::entity entity)
        {
            return true;
        }
        inline virtual void realTimePosition(ComponentBody *body) {}
    };

}

#endif
